package TokenRecognizer;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author jefoutta
 */
import java.util.*;

public class Subset {

    //private LinkedList<LinkedList<State>> afdStateList = new LinkedList();
    //private LinkedHashSet<LinkedHashSet<State>> afdStateSet = new LinkedHashSet();
    private Sets<Sets<State>> afdStateSet = new Sets();
    private LinkedList<State> afdStateList = new LinkedList();
    //private LinkedList<String> afdString = new LinkedList();
    private Automata afn = new Automata();
    private String sigma;

    public void setAutomata(Automata a1){
        afn.join(a1);
        sigma = a1.getSigma();
        System.out.println("sigma:" + sigma);
    }

    public Automata subSet(){
        Automata tautomata = new Automata();
        Sets<State> set1 = new Sets();
        afdStateSet.add(eLock(afn.getFirstState()));
        //afdString.add(afdStateSet.get(0).toString());
        State st1 = new State(afdStateSet.get(0));
        State st2 = null;
        afdStateList.add(st1);
        int i = 0;
        do{
            st1 = afdStateList.get(i);
            if(i == 0)
                tautomata.addLastState(st1);
            for(int j = 0; j < sigma.length() ; j++){
                set1 = eLock(move(afdStateSet.get(i), new Transition(sigma.charAt(j))));
                if(!afdStateSet.contains(set1)){
                    afdStateSet.add(set1);
                    //st2 = new State(afdStateSet.get(set1));
                    st2 = new State(afdStateSet.get(afdStateSet.indexOf(set1)));
                    afdStateList.add(st2);
                    tautomata.addLastState(st2);
                }else{
                    st2 = afdStateList.get(afdStateSet.indexOf(set1));
                }
                tautomata.setTransition(st1, st2, new Transition(sigma.charAt(j)));
            }
            i++;
        }while(i < afdStateSet.getSize());
        return tautomata;
    }

    public Sets<State> eLock(State s){
        Sets<State> afnStateSet = new Sets();
        Integer k = 0;
        do{
            for(int i = 0; i < afn.getSize(); i++){
                if(afn.getTransition(s, afn.getState(i)) != null){
                    if(afn.getTransition(s, afn.getState(i)).getLabel() == 'e'){
                        if(!afnStateSet.contains(afn.getState(i))){
                            afnStateSet.add(afn.getState(i));
                        }
                    }
                }
            }
            k++;
            if(k < afnStateSet.getSize())
                s = afnStateSet.get(k);
        }while(k < afnStateSet.getSize());

        /*if(!afdStateSet.contains(afnStateSet)){
            afdStateSet.add(afnStateSet);
        }*/
        return afnStateSet;
    }

    public Sets<State> eLock(Sets<State> set1){
        Sets<State> tset = new Sets();
        for(int i = 0; i < set1.getSize(); i++){
            tset.union(eLock(set1.get(i)));
        }
        return tset;
    }

    public Sets<State> move(State s,Transition t){
        Sets<State> afnStateSet = new Sets();
        Integer k = 0;
        do{
            for(int i = 0; i < afn.getSize(); i++){
                if(afn.getTransition(s, afn.getState(i)) != null){
                    if(afn.getTransition(s, afn.getState(i)).getLabel() == t.getLabel()){
                        if(!afnStateSet.contains(afn.getState(i))){
                            afnStateSet.add(afn.getState(i));
                        }
                    }
                }
            }
            k++;
            if(k < afnStateSet.getSize())
                s = afnStateSet.get(k);
        }while(k < afnStateSet.getSize());

        return afnStateSet;
    }

    public Sets<State> move(Sets<State> set1, Transition t){
        Sets<State> tset = new Sets();
        for(int i = 0; i < set1.getSize(); i++){
            tset.union(move(set1.get(i), t));
        }
        return tset;
    }

    public String toString(){
        return afdStateSet.toString();
    }
}
